package com.ftx.dao.aop;

import com.ftx.common.aspect.ChooseDataSource;
import com.ftx.common.aspect.DataSourceHandler;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.lang.builder.ReflectionToStringBuilder;
import org.apache.commons.lang.builder.ToStringStyle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Created by wangxindong on 2016/11/7.
 */
public class DaoUmpInterceptor implements MethodInterceptor {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());
    private String dbType;
    private String packageName;

//    /**
//     * mapper后置增强链
//     */
//    private static final List<PostMapperAdvice> POST_MAPPER_ADVICE_CHAIN = new ArrayList<PostMapperAdvice>();


    public Object invoke(MethodInvocation invocation) throws Throwable {
        //过滤包名
        if (!invocation.getMethod().getDeclaringClass().getName().startsWith(packageName))
            return invocation.proceed();
        try {
            dataSourceAspect(invocation);
            System.out.println("获取当前数据源为：" + DataSourceHandler.getDataSource());
            Object result = invocation.proceed();
            DataSourceHandler.reset();
            return result;
        } catch (Throwable e) {
            logException(invocation, e);
            throw e;
        } finally {
        }
    }

    private void logException(MethodInvocation invocation, Throwable e) {
        logger.error("DaoLayerError. dbType:[{}], method:[{}]#[{}], args:[{}], msg:[{}]",
                this.dbType,
                invocation.getMethod().getDeclaringClass().getSimpleName(),
                invocation.getMethod().getName(),
                getArguments4Log(invocation.getArguments()),
                e.getMessage(),
                e);
    }

    private String getArguments4Log(Object[] args) {
        if (args == null || args.length == 0) {
            return "WITHOUT_ARG";
        }
        try {
            StringBuilder sb = new StringBuilder();
            for (Object o : args) {
                sb.append(",");
                if (o == null) {
                    sb.append("null");
                    continue;
                }
                if (o.getClass().getPackage().getName().startsWith(packageName)) {
                    sb.append(ReflectionToStringBuilder.toString(o, ToStringStyle.SHORT_PREFIX_STYLE));
                } else {
                    sb.append('{');
                    sb.append(o);
                    sb.append('}');
                }
            }
            if (sb.length() > 0) {
                sb.deleteCharAt(0);
            }
            return sb.toString();
        } catch (Exception e) {
            logger.error("getArguments4Log error.", e);
        }
        return "ERROR_ARG";
    }

    /**
     * 数据源切换
     */
    private void dataSourceAspect(MethodInvocation invocation) {
        try {
            String method = invocation.getMethod().getName();
            System.out.println("dataSourceAspect method is " + method);
            for (String key : ChooseDataSource.METHOD_TYPE_MAP.keySet()) {
                System.out.println("dataSourceAspect key is " + key);
                for (String type : ChooseDataSource.METHOD_TYPE_MAP.get(key)) {
                    if (method.startsWith(type)) {
                        System.out.println("dataSourceAspect type is " + type);
                        DataSourceHandler.putDataSource(key);
                        return;
                    }
                }
            }
        } catch (Exception e) {
            logger.error("DaoUmpInterceptor --> dataSourceAspect 数据源切换异常", e);
        }
    }

    public void setDbType(String dbType) {
        this.dbType = dbType;
    }

    public void setPackageName(String packageName) {
        this.packageName = packageName;
    }

}
